iT邦幫忙

2024 iThome 鐵人賽

DAY 5
0
Software Development

我命由我不由語言 java爬蟲挑戰系列 第 5

Java爬蟲挑戰 Day 5 - Spring boot專案建立 & Jsoup爬取HTML資料

  • 分享至 

  • xImage
  •  

今天我們開始實際開發,重點是建立Spring boot專案。

GitHub連結

以後程式碼的改動都會使用此git
https://github.com/a951753sxd/rental-crawler

使用 Spring Initializr 建立專案

首先,我們利用 Spring Initializr 建立了一個 Java Maven 專案。
https://ithelp.ithome.com.tw/upload/images/20240822/20168635stLWuNgZta.png

Maven Pom.xml 說明

簡要說明一下依賴到哪些工具

  • Spring Boot Starter
    spring-boot-starter 是 Spring Boot 的核心啟動器,包含了 Spring Framework 以及其他必要的庫,能夠快速搭建 Spring 應用。
  • Spring Boot Test
    spring-boot-starter-test 是一個 Spring Boot 測試模組,提供了常見的測試庫和功能,如 JUnit、Mockito 等,用於編寫和運行單元測試。
  • Logback
    logback-classic 是 Logback 的核心模組,用於日誌記錄。Logback 是目前 Spring Boot 的預設日誌系統。
  • Jsoup
    jsoup 是一個用於解析 HTML 的 Java 庫,適合用來編寫網頁爬蟲。
  • Selenium
    selenium-java 是 Selenium 的 Java 綁定庫,用於自動化瀏覽器操作,適合處理動態加載的網頁。

logback.xml 設定

定義Log的層級、格式等...

<!-- logback.xml -->

<configuration>

    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>[%d][%p][%t][%C{0}:%L]: %msg%n</pattern>
        </encoder>
    </appender>

    <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>logs/app.log</file>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <Pattern>
				<pattern>[%d][%p][%t][%C{0}:%L]: %msg%n</pattern>
            </Pattern>
        </encoder>

        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- rollover daily -->
            <fileNamePattern>logs/app.%d{yyyy-MM-dd}.%i.log
            </fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
    </appender>

    <root level="info">
        <appender-ref ref="console" />
        <appender-ref ref="file" />
    </root>

</configuration>

建立 Service 及 Interface

RentalCrawlerService.java

接著,我們在專案中建立了一個 RentalCrawlerService 介面。
目前只有一個方法,為抓取資料

package tw.grass.rental_crawler.service;

public interface RentalCrawlerService {
    void fetchRentalData();
}

RentalCrawlerServiceImpl.java.

實作類別 RentalCrawlerServiceImpl
切分介面與實作,這樣的設計有助於未來進行擴展和測試。

package tw.grass.rental_crawler.service.impl;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.springframework.stereotype.Service;

import tw.grass.rental_crawler.service.RentalCrawlerService;

@Service
public class RentalCrawlerServiceImpl implements RentalCrawlerService {

    Logger log = LoggerFactory.getLogger(RentalCrawlerService.class);

    @Override
    public void fetchRentalData() {
        log.info("Starting to fetch rental data...");
        try {
            //這邊使用591的條件other=newPost:新上架、sort=posttime_desc:排序為新到舊
            String urlString = "https://rent.591.com.tw/list?other=newPost&sort=posttime_desc";

            // 提取連結中的HTML資訊
            Document doc = Jsoup.connect(urlString).get();
            // 在這裡解析HTML並提取所需數據
            parseHTML(doc);


            log.info("Successfully fetched rental data");
        } catch (Exception e) {
            log.error("Error while fetching rental data", e);
        }
    }

    //TODO: 處理資料邏輯代寫
    private void parseHTML(Document doc) {
    }
}

StartupRunner.java

那服務完成後,目前沒有程式進入點
目前為啟動程式一次,就去爬取資料一次
Autowired我們的Service後 執行fetchRentalData

package tw.grass.rental_crawler;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

import tw.grass.rental_crawler.service.RentalCrawlerService;

@Component
public class StartupRunner implements ApplicationRunner {

    @Autowired
    RentalCrawlerService rentalCrawlerService;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        rentalCrawlerService.fetchRentalData();
    }
}

目前的專案結構

目前的專案長這樣,還是建議直接拉git看,會比較清楚。
https://ithelp.ithome.com.tw/upload/images/20240822/201686350xp7Tr0sb9.png

Git狀況

https://ithelp.ithome.com.tw/upload/images/20240822/201686353pSgTCqhqY.png

實際執行

https://ithelp.ithome.com.tw/upload/images/20240822/201686352WcwO0OkdV.png

這個錯誤是由於 SSL 握手失敗引起的,具體來說是因為 Java 無法建立與目標網站的安全連接。
總之就是Java不信任591這個網站。

小結

今天我們完成了專案架構的搭建,並開始編寫爬蟲邏輯。同時,透過 Logback 的設置,我們能夠有效地追蹤爬蟲執行過程中的各種訊息。

明天我們將處理 SSL 憑證驗證問題,這在抓取一些需要安全連接的網站時非常關鍵。隨著專案逐步推進,我們也會進一步優化爬蟲邏輯和資料提取方法。


上一篇
java爬蟲挑戰 Day 4 - 591租屋爬蟲 需求分析&系統設計
下一篇
java爬蟲挑戰 Day 6 - Java導入SSL証書
系列文
我命由我不由語言 java爬蟲挑戰30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言